package com.bci.pwtz.controller;

/*
 * @FileName: [AbstractController.java]
 * 
 * @Package com.bcinfo.upp.admin.controller
 * 
 * 
 * Copyright (c) 2011-2015 BCINFO Technology Limited Com. All rights reserved.
 * 
 * This software is the confidential and proprietary information of BCINFO
 * Technology Limited Company ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in accordance
 * with the terms of the contract agreement you entered into with RKY.
 * 
 * $Rev: 3377 $ $LastChangedDate: 2013-11-06 13:33:28 +0800 (星期三, 06 十一月 2013) $
 * $LastChangedBy: lengzq $
 * 
 * @category bcinfo-upp
 * 
 * @version 1.1
 * 
 * @author $Author: lengzq $
 * 
 * Change History:[Formatter: author date description] <br/> 1 2 3
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;

import com.bci.pwtz.common.PwtzConstants;
import com.bci.pwtz.common.util.JsonUtils;
import com.bci.pwtz.common.util.PwtzUtils;
import com.bci.pwtz.common.util.SHA256Cryptor;
import com.bci.pwtz.exception.PwtzDatabaseException;
import com.bci.pwtz.exception.PwtzException;
import com.bci.pwtz.mysql.model.BusinessOperateLog;
import com.bci.pwtz.mysql.model.CompanyUser;
import com.bci.pwtz.service.BusinessOperateLogService;
import com.bci.pwtz.service.CompanyRoleService;
import com.bci.pwtz.service.ConfigService;

/**
 * 抽象的控制器 <br/>
 * <p>
 * Description:<br/>
 * <p>
 * 提供公共的控制器方法、属性
 * 
 * <p>
 * For Examples <br/>
 * 
 * <PRE>
 * public class XxxControler extends AbstractController
 * </PRE>
 * <p>
 */
public abstract class AbstractController
{
    protected final Logger            _log      = Logger.getLogger(this.getClass());

    /**
     * @Fields page : 分页页数，默认第一页
     */
    private int                       _page     = 1;

    /**
     * @Fields pageSize : 列表显示数量，默认为10条
     */
    private int                       _pageSize = 10;

    /**
     * @Fields request : 自动注入的HttpServletRequest 变量
     */
    @Autowired
    protected HttpServletRequest      request;

    /**
     * @Fields session : 自动注入的HttpSession变量
     */
    @Autowired
    protected HttpSession             session;

    /**
     * @Fields propertiesFactorBean : properties bean
     */
    @Autowired
    protected PropertiesFactoryBean   _propertiesFactorBean;

    @Autowired
    private ConfigService             configureService;

    @Autowired
    private BusinessOperateLogService businessOperateLogService;
    
    @Autowired
    private CompanyRoleService companyRoleService;
    /**
     * 生成token <br/>
     * <p>
     * Description: 每个form表单生成 一个token <br/>
     * <p>
     * Author: yun<br/>
     * <p>
     * Date: 2013-6-21-下午4:52:11<br/>
     * <p>
     * 
     * @return
     * 
     */
    @SuppressWarnings("unchecked")
    protected String generateToken()
    {
        Object obj = session.getAttribute("tokenStore");
        String token = DigestUtils.md5Hex(session.getId() + System.currentTimeMillis());
        Map<String, Date> tokenStore;

        if (obj == null)
        {
            tokenStore = new ConcurrentHashMap<String, Date>();
        }
        else
        {
            tokenStore = (Map<String, Date>) session.getAttribute("tokenStore");
        }

        tokenStore.put(token, new Date());
        session.setAttribute("tokenStore", tokenStore);

        return token;
    }

    /**
     * 获取错误信息 <br/>
     * <p>
     * Description: 通过异常名获取返回的错误信息 <br/>
     * <p>
     * Author: yun<br/>
     * <p>
     * Date: 2013-4-25-上午10:54:20<br/>
     * <p>
     * 
     * @param exceptionName
     * @return 异常对应的错误信息
     * 
     */
    protected String getErrorMessage(String exceptionName)
    {
        try
        {
            return ((Properties) (_propertiesFactorBean.getObject())).getProperty(exceptionName);
        }
        catch (IOException e)
        {
            handleException(e);
            return "错误信息配置文件加载错误";
        }
    }

    protected int getPage()
    {
        String pageString = request.getParameter("page");

        if (StringUtils.isNotBlank(pageString))
        {
            return Integer.parseInt(pageString);
        }

        return _page;
    }

    protected int getPageSize()
    {
        String pageSizeString = request.getParameter("rows");

        if (StringUtils.isNotBlank(pageSizeString))
        {
            return Integer.parseInt(pageSizeString);
        }

        return _pageSize;
    }

    /**
     * 封装ajax返回Map的信息<br/>
     * <p>
     * Description: 将ajax方法返回的Map信息进行统一的封装，使用时只需调用此方法传入参数即可。<br>
     * <p>
     * 如果自定义消息customMsgDesc不为空则使用customMsgDesc，否则根据msgDesc去查找相应的异常信息。 <br/>
     * <p>
     * Author: yun<br/>
     * <p>
     * Date: 2013-6-6-下午2:49:13<br/>
     * <p>
     * 
     * @param opResult
     *            结果
     * @param msgType
     *            消息类型
     * @param msgDesc
     *            消息描述
     * @param customMsgDesc
     *            自定义消息
     * @return
     * 
     */
    protected Map<String, String> packageAjaxReturnMap(String opResult, String msgType, String msgDesc, String customMsgDesc)
    {
        Map<String, String> map = new HashMap<String, String>(10);

        map.put(ERROR_KEY_OP_RESULT, opResult);
        map.put(ERROR_KEY_MSG_TYPE, msgType);

        if (StringUtils.isNotBlank(customMsgDesc))
        {
            map.put(ERROR_KEY_MSG_DESC, customMsgDesc);
        }
        else
        {
            map.put(ERROR_KEY_MSG_DESC, getErrorMessage(msgDesc));
        }

        return map;

    }

    /**
     * 异常封装 <br/>
     * <p>
     * Description: 将繁琐的异常捕获用一个统一的方法来封装并返回封装后的Map <br/>
     * <p>
     * Author: yun<br/>
     * <p>
     * Date: 2013-5-23-下午5:55:10<br/>
     * <p>
     * 
     * @param e
     * @return
     * 
     */
    protected Map<String, String> packageUppException(PwtzException e)
    {
        handleException(e);

        Map<String, String> map = new HashMap<String, String>(4);
        map = packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_FAIL, ERROR_VALUE_MSG_TYPE_ERROR, "", e.getMessage());

        return map;
    }

    /**
     * 异常封装 <br/>
     * <p>
     * Description: 将繁琐的异常捕获用一个统一的方法来封装并返回封装后的Map <br/>
     * <p>
     * Author: yun<br/>
     * <p>
     * Date: 2013-5-23-下午5:55:10<br/>
     * <p>
     * 
     * @param e
     * @return
     * 
     */
    protected Map<String, String> packageException(Exception e)
    {
        handleException(e);

        Map<String, String> map = new HashMap<String, String>(4);

        if (e instanceof ParseException)
        {
            map = packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_FAIL, ERROR_VALUE_MSG_TYPE_ERROR, "ParseException", e.getMessage());
        }
        else
        {
            map = packageAjaxReturnMap(ERROR_VALUE_OP_RESULT_FAIL, ERROR_VALUE_MSG_TYPE_ERROR, "UnknowException", e.getMessage());
        }

        return map;
    }

    /**
     * 普通异常处理 <br/>
     * <p>
     * Description: 记录日志、不封装、不返回对象 <br/>
     * <p>
     * Author: yun<br/>
     * <p>
     * Date: 2013-5-24-上午9:23:52<br/>
     * <p>
     * 
     * @param e
     * 
     */
    protected void handleException(Exception e)
    {
        _log.error(ExceptionUtils.getStackTrace(e));
    }

    /**
     * @Fields ERROR_KEY_MSG_TYPE : 返回值的key msgType
     */
    public static final String ERROR_KEY_MSG_TYPE                 = "msgType";

    /**
     * @Fields ERROR_KEY_MSG_DESC : 返回值的key msgDesc
     */
    public static final String ERROR_KEY_MSG_DESC                 = "msgDesc";

    /**
     * @Fields ERROR_KEY_OP_RESULT : 返回值的key opResult
     */
    public static final String ERROR_KEY_OP_RESULT                = "opResult";

    /**
     * @Fields ERROR_VALUE_MSG_TYPE_INFO : 返回值的value 消息
     */
    public static final String ERROR_VALUE_MSG_TYPE_INFO          = "info";

    /**
     * @Fields ERROR_VALUE_MSG_TYPE_WARN : 返回值的value 警告
     */
    public static final String ERROR_VALUE_MSG_TYPE_WARN          = "warning";

    /**
     * @Fields ERROR_VALUE_MSG_TYPE_QUESTION : 返回值的value 疑问
     */
    public static final String ERROR_VALUE_MSG_TYPE_QUESTION      = "question";

    /**
     * @Fields ERROR_VALUE_MSG_TYPE_ERROR : 返回值的value 错误
     */
    public static final String ERROR_VALUE_MSG_TYPE_ERROR         = "error";

    /**
     * @Fields ERROR_VALUE_OP_RESULT_SUCCESS : 返回值操作结果 成功
     */
    public static final String ERROR_VALUE_OP_RESULT_SUCCESS      = "0";

    /**
     * @Fields ERROR_VALUE_OP_RESULT_FAIL : 返回值操作结果 失败
     */
    public static final String ERROR_VALUE_OP_RESULT_FAIL         = "1";

    /**
     * @Fields ZTREE_ROOT_VALUE : ztree 根节点的值
     */
    public static final String ZTREE_ROOT_NODE_VALUE              = "-1";

    /**
     * @Fields ERROR_VALUE_OP_RESULT_SUCCESS_NAME : 获取操作结果 成功字段
     */
    public static final String ERROR_VALUE_OP_RESULT_SUCCESS_NAME = "Success";

    public static final int    add                                = 1;

    public static final int    update                             = 2;

    public static final int    delete                             = 3;

    public static final int    配电变压器                              = 1;
    public static final int    柱上变压器                              = 2;
    public static final int    低压线路                               = 3;
    public static final int    低压杆塔                               = 4;
    public static final int    低压导线                               = 5;
    public static final int    低压柱上开关                             = 6;
    public static final int    低压柱上熔断器                            = 7;
    public static final int    低压熔丝箱                              = 8;
    public static final int    低压熔丝                               = 9;
    public static final int    低压柱上电容器                            = 10;
    public static final int    低压无功补偿装置                           = 11;
    public static final int    低压柱上避雷器                            = 12;
    public static final int    低压电缆                               = 13;
    public static final int    低压电缆终端                             = 14;
    public static final int    低压电缆接头                             = 15;
    public static final int    低压配电箱                              = 16;
    public static final int    低压电缆分接箱                            = 17;
    public static final int    低压开关                               = 18;
    public static final int    低压母线                               = 19;
    public static final int    低压配电盘                              = 20;
    public static final int    低压开关柜                              = 21;
    public static final int    反孤岛装置                              = 22;
    public static final int    低压剩余电流保护器                          = 23;
    public static final int    低压表箱                               = 24;
    public static final int    低压交叉跨越                             = 25;
    public static final int    低压用户接入点                              = 26;
    public static final int    变电站                                = 100;
    public static final int    中压线路                               = 101;
    public static final int    中压杆塔                               = 102;
    public static final int    中压柱上杆变分接表                          = 103;
    public static final int    中压柱上断路器                            = 104;
    public static final int    中压柱上负荷开关                           = 105;
    public static final int    中压柱上隔离开关                           = 106;
    public static final int    中压柱上重合器                            = 107;
    public static final int    中压柱上跌落式熔断器                         = 108;
    public static final int    中压柱上避雷器                            = 109;
    public static final int    中压柱上故障指示器                          = 110;
    public static final int    中压柱上电容器                            = 111;
    public static final int    中压柱上电压互感器                          = 112;
    public static final int    中压柱上电流互感器                          = 113;
    public static final int    中压柱上组合互感器                          = 114;
    public static final int    中压柱上分段器                            = 115;
    public static final int    中压柱上调容变压器                          = 116;
    public static final int    中压柱上自动调压器                          = 117;
    public static final int    中压柱上附属设备                           = 118;
    public static final int    中压导线                               = 119;
    public static final int    中压电缆                               = 120;
    public static final int    中压电缆终端                             = 121;
    public static final int    中压电缆接头                             = 122;
    public static final int    中压交叉跨越                             = 123;
    public static final int    中压开关站                              = 124;
    public static final int    中压配电室                              = 125;
    public static final int    中压环网柜                              = 126;
    public static final int    中压箱式变电站                            = 127;
    public static final int    中压电缆分支箱                            = 128;
    public static final int    中压站内间隔单元                           = 129;
    public static final int    中压站内所用变                            = 130;
    public static final int    中压站内断路器                            = 131;
    public static final int    中压站内隔离开关                           = 132;
    public static final int    中压站内负荷开关                           = 133;
    public static final int    中压站内熔断器                            = 134;
    public static final int    中压站内母线                             = 135;
    public static final int    中压站内电抗器                            = 136;
    public static final int    中压站内电流互感器                          = 137;
    public static final int    中压站内电压互感器                          = 138;
    public static final int    中压站内组合互感器                          = 139;
    public static final int    中压站内电力电容器                          = 140;
    public static final int    中压站内避雷器                            = 141;
    public static final int    中压站内开关柜                            = 142;
    public static final int    中压站内故障指示器                          = 143;
    public static final int    中压电缆井                                =144;
    public static final int    中压电缆井关联                              =145;
    /**
     * 获取系统配置 <br/>
     * <p>
     * Description: 根据传入的key查询系统配置的值 <br/>
     * <br/>
     * <p>
     * Author: tonic<br/>
     * <p>
     * Date: 2014-9-16-下午2:08:24<br/>
     * <p>
     * 
     * @param key
     * @return
     * @throws PwtzDatabaseException
     * 
     */
    protected String getConfigByKey(String key) throws PwtzDatabaseException
    {
        return configureService.getConfigByKey(key);
    }

    /**
     * 
     * 验证密钥 <br/>
     * <p>
     * Description: TODO(详细描述) <br/>
     * <p>
     * Author: tonic<br/>
     * <p>
     * Date: 2014-9-25-上午11:26:12<br/>
     * <p>
     * 
     * @param key
     * @param timestamp
     * @return
     * @throws PwtzDatabaseException
     * 
     */
    protected boolean validateSecretKey(String key, String timestamp) throws PwtzDatabaseException
    {
        boolean bl = false;
        String str = PwtzConstants.INTERFACE_SCRECTKEY + timestamp;
        // 加密
        str = SHA256Cryptor.sha256Encrypt(str);
        if (str.equals(key))
        {
            bl = true;
        }
        return bl;
    }

    /**
     * 
     * 验证TOKEN <br/>
     * <p>
     * Description: TODO(详细描述) <br/>
     * <p>
     * Author: tonic<br/>
     * <p>
     * Date: 2014-9-25-上午11:25:55<br/>
     * <p>
     * 
     * @param token
     * @param userId
     * @return
     * @throws PwtzDatabaseException
     * 
     */
    protected boolean validateToken(String token, Long userId) throws PwtzDatabaseException
    {
        boolean bl = false;
        if (token != null)
        {
            if (PwtzConstants.TOKEN_MAP.containsKey(token + userId))
            {
                PwtzConstants.TOKEN_MAP.put(token + userId, PwtzUtils.getMinuteAfter(new Date(), PwtzConstants.TOKEN_VAILD));
                bl = true;
            }
        }

        return bl;
    }

    /**
     * 
     * 获取REQ对象 <br/>
     * <p>
     * Description: TODO(详细描述) <br/>
     * <p>
     * Author: tonic<br/>
     * <p>
     * Date: 2014-9-25-上午11:25:16<br/>
     * <p>
     * 
     * @param request
     * @param t
     * @return
     * 
     */
    protected <T> T getJsonToObj(HttpServletRequest request, Class<T> t)
    {
        String json = "";
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream(), "UTF-8"));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null)
            {
                sb.append(line);
            }
            json = sb.toString();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return JsonUtils.json2bean(json, t);
    }

    /**
     * 
     * 记录日志 <br/>
     * <p>
     * Description: TODO(详细描述) <br/>
     * <p>
     * Author: tonic<br/>
     * <p>
     * Date: 2014-9-25-上午11:25:02<br/>
     * <p>
     * 
     * @param deviceId
     * @param companyId
     * @param deviceTypeId
     * @param action
     * @param content
     * @param operatorId
     * 
     */
    protected void setLog(String deviceId, Long companyId, Integer deviceTypeId, Integer action, String content, Long operatorId)
    {
        BusinessOperateLog log = new BusinessOperateLog();
        log.setDeviceId(deviceId);
        log.setCompanyId(companyId);
        log.setDeviceTypeId(deviceTypeId);
        log.setAction(action);
        log.setContent(content);
        log.setOperatorId(operatorId);
        log.setCreateTime(new Date());
        try
        {
            businessOperateLogService.add(log);
        }
        catch (PwtzDatabaseException e)
        {
            e.printStackTrace();
        }
    }

    protected CompanyUser getUser()
    {
        return (CompanyUser) session.getAttribute("user");
    }

    protected Long getUserId()
    {
        return (Long) session.getAttribute("userId");
    }

    protected Long getLastCompanyId()
    {
        return ((CompanyUser) session.getAttribute("user")).getLastCompanyId();
    }
    
    protected List<String> getCurrentAction(){
        List<String> actionList=new ArrayList<String>();
        Long userId=((CompanyUser) session.getAttribute("user")).getCompanyUserId();
        Long companyId=((CompanyUser) session.getAttribute("user")).getLastCompanyId();
        try
        {
            actionList=companyRoleService.selectRoleAction(companyId, userId);
        }
        catch (PwtzDatabaseException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return actionList;
    }
    
    public static boolean isHasAction(String actionCode,List<String> actionList){
        if(actionList!=null&&actionList.size()>0){
            for(String action:actionList){
                if(action.equals(actionCode)){
                    return true;
                }
            }
        }
        return false;
    }
    
    public String[] decodeURL(String[] datas) throws UnsupportedEncodingException{
    	if(datas != null && datas.length > 0){
    		for(int i = 0; i < datas.length; i++){
    			if(datas[i] != null && datas.length > 0){
    				datas[i] = URLDecoder.decode(datas[i],"utf-8");
    			}
    		}
    		return datas;
    	}
    	return null;
    }
}